import os
import sys
import re

class GetUserInput(object):

    def __init__(self):
        self.typeDict = {'bool': self._bool,
                         'file': self._fname,
                         'multi': self._multi,
                         'raw': self._rawText,
                         'num': self._number,
                         'ip': self._ipaddress}

    def ask(self, question, atype, akey=None):
        print ''
        try:
            answer = raw_input('{} > '.format(question))
        except KeyboardInterrupt:
            print 'Input not recognized.  Enter valid response or \'q\' to quit.'
            self.ask(question, atype, akey)
        else:
            if answer == 'q': sys.exit()
        response = self.typeDict[atype](answer, akey)
        if response is None:
            print 'Invalid response.'
            self.ask(question, atype, akey)
        return response

    def _multi(self, answer, akey):
        if answer.lower() not in akey: return None
        return answer

    def _bool(self, answer, akey=None):
        pos = ['y', 'yes', 'true', '1']
        neg = ['n', 'no', 'false', '0']
        try:
            if answer.lower() in pos: answer = True
            elif answer.lower() in neg: answer = False
            else: answer = None
        except:
            answer = None
        return answer

    def _fname(self, answer, akey=None):
        if not answer:
            print 'No file provided.'
            return False
        elif '.csv' not in answer.lower():
            print 'Files must be CSV.'
            return None
        elif not os.path.exists(answer):
            print 'File not found.'
            return None
        else:
            return answer

    def _rawText(self, answer, akey=None):
        return answer

    def _number(self, answer, akey=None):
        try:
            answer = int(answer)
        except (ValueError, TypeError):
            print 'Response must be an integer.'
            answer = None
        else:
            if akey and answer not in akey:
                answer = None
        return answer

    def _ipaddress(self, answer):
        ip = re.compile(r'^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$')
        octs = re.match(ip, answer)
        if not octs:
            return None
        elif any(e for e in octs.groups() if (int(e) > 255 or int(e) < 0)):
            return None
        return answer
